﻿using Swifter.Data.Sql;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq.Expressions;


namespace Swifter.Data.Linq
{
    /// <summary>
    /// 数据查询器。
    /// </summary>
    /// <typeparam name="TSource">实体类</typeparam>
    [EditorBrowsable(EditorBrowsableState.Never)]
    public class DbQuery<TSource>
    {
        /// <summary>
        /// 数据库实例。
        /// </summary>
        public Database Database { get; }

        internal SelectStatement SelectStatement { get; }

        internal DbQuery(Database database, SelectStatement selectStatement)
        {
            SelectStatement = selectStatement;
            Database = database;
        }

        /// <summary>
        /// 设置查询条件。
        /// </summary>
        /// <param name="predicate">条件表达式</param>
        /// <returns>返回一个新的查询器</returns>
        public DbQuery<TSource> Where(Expression<Func<TSource, bool>> predicate)
        {
            var select = new SelectStatement(SelectStatement);

            var scope = new ScopeInfo
            {
                GetTable = item => item == predicate.Parameters[0] ? SelectStatement : null
            };

            select.Where.Add(Visiter.Default.Process<Condition>(scope, predicate.Body));

            return new DbQuery<TSource>(Database, select);
        }

        /// <summary>
        /// 选择结果的类型。
        /// </summary>
        /// <typeparam name="TResult">新结果类型</typeparam>
        /// <param name="selector">选择表达式</param>
        /// <returns>返回一个新的查询器</returns>
        public DbQuery<TResult> Select<TResult>(Expression<Func<TSource, TResult>> selector)
        {
            var select = new SelectStatement(SelectStatement);

            var scope = new ScopeInfo
            {
                GetTable = item => item == selector.Parameters[0] ? SelectStatement : null
            };

            foreach (var item in Visiter.Default.Process<IEnumerable<ISelectColumn>>(scope, selector.Body))
            {
                select.Columns.Add(item);
            }

            return new DbQuery<TResult>(Database, select);
        }

        /// <summary>
        /// 设置排序值。
        /// </summary>
        /// <typeparam name="TKey">排序值的类型</typeparam>
        /// <param name="keySelector">排序列表达式</param>
        /// <param name="direction">排序方向</param>
        /// <returns>返回新的查询器</returns>
        public DbQuery<TSource> OrderBy<TKey>(Expression<Func<TSource, TKey>> keySelector, OrderByDirections direction = OrderByDirections.ASC)
        {
            var select = SelectStatement.Clone();

            var scope = new ScopeInfo
            {
                GetTable = item => item == keySelector.Parameters[0] ? SelectStatement : null
            };

            select.OrderBys.Add(new OrderBy(Visiter.Default.Process<Column>(scope, keySelector.Body), direction));

            return new DbQuery<TSource>(Database, select);
        }

        /// <summary>
        /// 设置倒叙排序值。
        /// </summary>
        /// <typeparam name="TKey">排序值的类型</typeparam>
        /// <param name="keySelector">排序列表达式</param>
        /// <returns>返回新的查询器</returns>
        public DbQuery<TSource> OrderByDescending<TKey>(Expression<Func<TSource, TKey>> keySelector) => OrderBy(keySelector, OrderByDirections.DESC);

        ///// <summary>
        ///// 设置按结果集分组。
        ///// </summary>
        ///// <typeparam name="TKey">分组键的类型</typeparam>
        ///// <param name="keySelector">分组键</param>
        ///// <returns>返回新的查询器</returns>
        //public DbQuery<DbGrouped<TKey>> GroupBy<TKey>(Expression<Func<TSource, TKey>> keySelector)
        //{
        //    var select = new SelectStatement(SelectStatement);

        //    var scope = new ScopeInfo
        //    {
        //        GetTable = item => item == keySelector.Parameters[0] ? SelectStatement : null
        //    };

        //    var column = Visiter.Default.Process<Column>(scope, keySelector.Body);

        //    select.GroupBys.Add(column);

        //    return new DbQuery<TSource>(Database, select).Select(item => new DbGrouped<TKey>() { Key = keySelector(); });
        //}

        /// <summary>
        /// 查询当前数据量。
        /// </summary>
        /// <returns>返回数据数量</returns>
        public int Count() => CreateQuery<TSource>(e => e.CountOfColumn(SqlHelper.ValueOf(1), nameof(Count))).Execute<int>();

        /// <summary>
        /// 查询结果集中最大的结果（数据库默认比较方式）。
        /// </summary>
        /// <returns>返回结果</returns>
        public TSource Max() => OrderBy(item => item, OrderByDirections.DESC).Take(1).Execute<TSource>();

        /// <summary>
        /// 查询结果集中最小的结果（数据库默认比较方式）。
        /// </summary>
        /// <returns>返回结果</returns>
        public TSource Min() => OrderBy(item => item, OrderByDirections.ASC).Take(1).Execute<TSource>();

        /// <summary>
        /// 限制结果集行数数量。
        /// </summary>
        /// <param name="count">数量</param>
        /// <returns>返回新的查询器</returns>
        public DbQuery<TSource> Take(int count)
        {
            var select = SelectStatement.Clone();

            select.Limit = count;

            return new DbQuery<TSource>(Database, select);
        }

        /// <summary>
        /// 跳过结果集中指定数量的元素.
        /// </summary>
        /// <param name="count">数量</param>
        /// <returns>返回新的查询器</returns>
        public DbQuery<TSource> Skip(int count)
        {
            var select = SelectStatement.Clone();

            select.Offset = count;

            return new DbQuery<TSource>(Database, select);
        }

        /// <summary>
        /// 查询结果集中的第一个结果。 
        /// </summary>
        /// <returns>返回结果</returns>
        public TSource First()
        {
            var sources = Take(1).Execute<TSource[]>();

            if (sources.Length == 0)
            {
                throw new InvalidOperationException("The source sequence is empty.");
            }

            return sources[0];
        }

        /// <summary>
        /// 查询结果集中的第一个结果，如果结果集为空，则返回默认值。
        /// </summary>
        /// <returns>返回结果</returns>
        public TSource FirstOrDefault() => Take(1).Execute<TSource>();

        private DbQuery<T> CreateQuery<T>(Action<SelectStatement> action)
        {
            var selectStatement = new SelectStatement(SelectStatement);

            action(selectStatement);

            return new DbQuery<T>(Database, selectStatement);
        }

        internal TResult Execute<TResult>()
        {
            // TODO 优化

            Console.WriteLine(Database.BuildSelectStatement(SelectStatement).ToSql());

            return Database.ExecuteScalar<TResult>(Database.BuildSelectStatement(SelectStatement).ToSql());
        }

        /// <summary>
        /// 查询数据，并获取数据集的迭代器。
        /// </summary>
        /// <returns></returns>
        public IEnumerator<TSource> GetEnumerator() => Execute<List<TSource>>().GetEnumerator();

        /// <summary>
        /// 获取当前查询的 SQL 表现形式。
        /// </summary>
        /// <returns></returns>
        public string ToSql() => Database.BuildSelectStatement(SelectStatement).ToSql();
    }

    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="TKey"></typeparam>
    /// <typeparam name="TSource"></typeparam>
    public class DbGrouping<TKey, TSource>
    {
        public TKey Key => throw new NotSupportedException();

        public TValue Max<TValue>(Expression<Func<TSource, TValue>> valueSelector) => throw new NotSupportedException();

        public TValue Min<TValue>(Expression<Func<TSource, TValue>> valueSelector) => throw new NotSupportedException();

        public int Count() => throw new NotSupportedException();

        public static implicit operator DbGrouped<TKey>(DbGrouping<TKey, TSource> grouping) => throw new NotSupportedException();
    }

    public struct DbGrouped<TKey>
    {
        public TKey Key { get; set; }
    }
}